/*
 * MessageHeader.java    0.0.1    27/set/2009
 * 
 * Copyright (c) 2009 mentalsmash.org
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of the Apache License does not indicate that this project is
 * affiliated with the Apache Software Foundation.
 */ 
package org.mentalsmash.tazio.net.cs.protocol;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.StreamCorruptedException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This class is a convenience class used to serialise and deserialise the header of a 
 * {@link NIOObjectContainer} instance, hiding the details of how an header is built.
 * @version    0.0.1    27/set/2009    
 * @author     Andrea Reale <andrea.reale@gmail.com>
 */
public final class MessageHeader {
  private final static transient Logger log = LoggerFactory.getLogger(NIOObjectContainer.class);
  /**
   * The size in bytes of the header of the externalised form of the container
   */
  public final static int HEADER_SIZE = (Integer.SIZE*2)/8;
  /**
   * A 4 bytes code delimiting the start of a new <tt>NIOObjectContainer</tt> serialisation stream.
   * <br />It currently is: <code>0xDEADCAFE</code>
   */
  public final static int START_MARKER = 0xDEADCAFE;
  

  private int payloadLength;

  protected MessageHeader() {

  }
  public MessageHeader(byte[] payLoad) {
    setPayloadLength(payLoad.length);
  }

  /**
   * Returns the length in bytes of the serialised representation of the payload object
   * @return the length in bytes of the serialised representation of the payload object
   */
  public int getPayloadLength() {
    return payloadLength;
  }

  /**
   * Sets the length of the payload of this <tt>NIOObjectContainer</tt>.
   * It must be non-negative.
   * @param payloadLength  the length of the payload of this <tt>NIOObjectContainer</tt>.
   */
  public void setPayloadLength(int payloadLength) {
    if (payloadLength < 0) {
      throw new IllegalArgumentException("Payload size must be non-negative");
    }

    this.payloadLength = payloadLength;
  }

  
  public byte[] writeHeader() throws IOException{
      ByteArrayOutputStream os = null;
      DataOutputStream dos = null;
      byte[] encodedHeader = null;
      
      try {
	  os = new ByteArrayOutputStream(HEADER_SIZE);
	  dos = new DataOutputStream(os);
	  dos.writeInt(START_MARKER);
	  dos.writeInt(getPayloadLength());
	  dos.flush();
	  encodedHeader = os.toByteArray();
      } finally {
	  os.close();
	  dos.close();
      }
      return encodedHeader;
  }
  
  public static MessageHeader readHeader(byte[] encodedHeader) throws IOException {
      DataInputStream dis = null;
      int startMarker;
      int payloadLength;
      MessageHeader toReturn;
      
      if (encodedHeader.length != HEADER_SIZE) {
	  String msg = "The encoded header must be " + HEADER_SIZE + " bytes long";
	  log.error(msg);
	  throw new IllegalArgumentException(msg);
      }
      
      try {
	  dis = new DataInputStream(new ByteArrayInputStream(encodedHeader));
	  startMarker = dis.readInt();
	  if(startMarker != MessageHeader.START_MARKER) {
	      String msg= "No start marker was found";
	      log.error(msg);
	      throw new StreamCorruptedException("No start marker was found");
	  }
	  payloadLength = dis.readInt();
      } finally {
	  dis.close();
      }
      
      toReturn =  new MessageHeader();
      toReturn.setPayloadLength(payloadLength);
      
      return toReturn;
      
  }
  

}

